﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Hosting;
using System.Reflection;
using System.IO;

namespace Host
{
    class AssemblyResourceProvider : System.Web.Hosting.VirtualPathProvider
    {

        public AssemblyResourceProvider()
        {
        }

        private bool IsAppResourcePath(string virtualPath)
        {
            string checkPath = VirtualPathUtility.ToAppRelative(virtualPath);

            //
            // Convencionamos que os recursos dentro de uma dll
            // serão acessados pelo radical "~/Plugins/"
            //
            return checkPath.StartsWith("~/Plugins/", StringComparison.InvariantCultureIgnoreCase);
        }

        public override bool FileExists(string virtualPath)
        {
            if (IsAppResourcePath(virtualPath))
            {
                string path = VirtualPathUtility.ToAppRelative(virtualPath);

                string[] parts = path.Split('/');

                string assemblyName = parts[2];
                string resourceName = parts[3];

                assemblyName = Path.Combine(HttpRuntime.BinDirectory, assemblyName);

                //
                // Carrega a dll em memória
                //
                byte[] assemblyBytes = File.ReadAllBytes(assemblyName);
                Assembly assembly = Assembly.Load(assemblyBytes);

                if (assembly != null)
                {
                    string[] resourceList = assembly.GetManifestResourceNames();

                    //
                    // Procura pelo resource em IgnoreCase
                    //
                    bool found = Array.Exists(resourceList, delegate(string r)
                    {
                        return r.Equals(resourceName, StringComparison.InvariantCultureIgnoreCase);
                    });

                    return found;
                }

                return false;
            }
            else
                return base.FileExists(virtualPath);
        }

        public override VirtualFile GetFile(string virtualPath)
        {
            if (IsAppResourcePath(virtualPath))

                //
                // Buscamos o recurso dentro de uma dll
                //
                return new AssemblyResourceVirtualFile(virtualPath);
            else

                //
                // Deixamos para a classe base resolver
                //
                return base.GetFile(virtualPath);
        }

        public override System.Web.Caching.CacheDependency GetCacheDependency(string virtualPath,
            System.Collections.IEnumerable virtualPathDependencies, DateTime utcStart)
        {
            if (IsAppResourcePath(virtualPath))

                //
                // Não fazemos caching
                //
                return null;
            else

                //
                // Pegamos o cache da classe base
                //
                return base.GetCacheDependency(virtualPath, virtualPathDependencies, utcStart);
        }

    }
}